#region Using Statements
using System;
using System.Collections.Generic;
//using System.Xml.Serialization;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.GamerServices;
#endregion

namespace Pauliver
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {

        #region Roll this into the ContentManager Constructor/Parameter
        private void SetupStorageDevice()
        {
            System.AsyncCallback callback = new AsyncCallback(StorageDeviceCallback);
            Guide.BeginShowStorageDeviceSelector(callback, null);

        }
        private void StorageDeviceCallback(IAsyncResult result)
        {
            storageDevice = Guide.EndShowStorageDeviceSelector(result);
        }
        protected StorageDevice storageDevice;
        public StorageDevice StorageDevice
        {
            get
            {
                return storageDevice;
            }
        }
        #endregion

        protected float seconds;
        public float SecondsSoFar
        {
            get
            {
                return seconds;
            }
        }

        #region Debug
        bool _debug = false;

        public bool Debug
        {
            get
            {
                return _debug;
            }
        }
        #endregion

        #region CurrentView
        private Rectangle _CurrentViewport;
        public Rectangle CurrentViewport
        {
            get
            {
                return _CurrentViewport;
            }
            set
            {
                _CurrentViewport = value;
            }
        }
        float _AspectRatio;
        public void Increase(int value)
        {
            int x = _CurrentViewport.X;
            int y = _CurrentViewport.Y;

            _CurrentViewport.Inflate((int)(value * _AspectRatio), (int)value);

            _CurrentViewport.X = x;
            _CurrentViewport.Y = y;

            if (_CurrentViewport.X < 0)
            {
                _CurrentViewport.X = 0;
            }
            if (_CurrentViewport.Y < 0)
            {
                _CurrentViewport.Y = 0;
            }
            if (_CurrentViewport.Width >= World.X || _CurrentViewport.Y >= World.Y)
            {
                _CurrentViewport = new Rectangle(0, 0,(int) World.X,(int) World.Y);
            }
        }
        public void Decrease(int value)
        {
            if (_CurrentViewport.Width == _graphics.PreferredBackBufferWidth || _CurrentViewport.Height == _graphics.PreferredBackBufferHeight)
            {
                _CurrentViewport.Width = _graphics.PreferredBackBufferWidth;
                _CurrentViewport.Height = _graphics.PreferredBackBufferHeight;
                if (_CurrentViewport.X < 0)
                {
                    _CurrentViewport.X = 0;
                }
                if (_CurrentViewport.Y < 0)
                {
                    _CurrentViewport.Y = 0;
                }
            }
            else
            {
                int x = _CurrentViewport.X;
                int y = _CurrentViewport.Y;

                _CurrentViewport.Inflate((int)(-1 * value * _AspectRatio), -1 * value);

                _CurrentViewport.X = x;
                _CurrentViewport.Y = y;
                if (_CurrentViewport.Width < _graphics.PreferredBackBufferWidth || _CurrentViewport.Height < _graphics.PreferredBackBufferHeight)
                {
                    _CurrentViewport.Width = _graphics.PreferredBackBufferWidth;
                    _CurrentViewport.Height = _graphics.PreferredBackBufferHeight;
                }
                if (_CurrentViewport.X < 0)
                {
                    _CurrentViewport.X = 0;
                }
                if (_CurrentViewport.Y < 0)
                {
                    _CurrentViewport.Y = 0;
                }
            }
        }
        bool IgnoreAllOtherFoci = false;
        public void CenterOn(Vector2 Position, bool IgnoreOther)
        {
            if (IgnoreOther)
            {
                int heigh = _CurrentViewport.Height;
                int width = _CurrentViewport.Width;
                int w2 = width / 2;
                int h2 = heigh / 2;
                _CurrentViewport.X = (int)(Position.X - w2);
                _CurrentViewport.Y = (int)(Position.Y - h2);
                IgnoreAllOtherFoci = IgnoreOther;
            }else if(IgnoreAllOtherFoci)
            {
                return;
            }
            if (!Slide)
            {
                int heigh = _CurrentViewport.Height;
                int width = _CurrentViewport.Width;
                int w2 = width / 2;
                int h2 = heigh / 2;
                _CurrentViewport.X = (int)(Position.X - w2);
                _CurrentViewport.Y = (int)(Position.Y - h2);
            }
        }
        public void CenterOn(Vector2 Position)
        {
            if (IgnoreAllOtherFoci)
            {
                return;
            }
            if (!Slide)
            {
                int heigh = _CurrentViewport.Height;
                int width = _CurrentViewport.Width;
                int w2 = width / 2;
                int h2 = heigh / 2;
                _CurrentViewport.X = (int)(Position.X - w2);
                _CurrentViewport.Y = (int)(Position.Y - h2);
            }
        }
        public void SlideTowards(Vector2 Position)
        {
            int heigh = _CurrentViewport.Height;
            int width = _CurrentViewport.Width;
            int w2 = width / 2;
            int h2 = heigh / 2;
            TargetPosition = Position - new Vector2(w2,h2);
            Slide = true;
        }
        Vector2 TargetPosition;
        bool Slide = false;
        #endregion

        int _fps;
        string fps = "FPS: 0";
        TimeSpan _time;

        #region GameManager stuff
        GameManager _CurrentGameManager;
        public GameManager GameManager
        {
            get
            {
                return _CurrentGameManager;
            }
        }
        public void EndGame()
        {
            _CurrentGameManager = null;
            _Collision = null;
            _CurrentLevel = null;

            System.GC.Collect();
            //reset teams to correct names
        }
        #endregion

        #region Menu Stuff
        private List<BaseMenu> _Menus;
        public BaseMenu CurrentMenu
        {
            get
            {
                if (_Menus.Count != 0)
                {
                    return _Menus[_Menus.Count - 1];
                }else{
                    return null;
                }
            }
            set
            {
                _Menus.Add(value);
            }
        }
        public void PopTopMenu()
        {
            if (_Menus.Count > 0)
                _Menus.RemoveAt(_Menus.Count - 1);


        }
        public void AddMenu(BaseMenu menu)
        {
            _Menus.Add(menu);
        }
        #endregion

        #region Game Instance
        private static Game1 _Instance;
        public static Game1 Instance
        {
            get
            {
                if (_Instance == null)
                {
                    _Instance = new Game1();
                }
                return _Instance;
            }
        }
        #endregion

        #region Error Handeling

        public static void Exception(Component p_me, ComponentType p_type)
        {
            if (p_me.Parent[p_type] == null)
            {
                throw new Exception("Component " + p_type.ToString() + " Does not exist on " + p_me.Parent.ToString());
            }
        }

        #endregion

        #region base code
        GraphicsDeviceManager _graphics;
        ContentManager _content;
        SpriteBatch _spriteBatch;
        Vector2 _WorldExtent;
        public Vector2 World
        {
            get { return _WorldExtent; }
        }
        #endregion

        private Game1()
        {
            _graphics = new GraphicsDeviceManager(this);
            _content = new ContentManager(Services);

#if PERPIXEL
            _WorldExtent = new Vector2( 1280, 720);
#else
            _WorldExtent = new Vector2( 1920, 800);
#endif
#if WINDOWS
            _graphics.PreferredBackBufferHeight = 320;
            _graphics.PreferredBackBufferWidth = 240;
#else
            _graphics.PreferredBackBufferHeight = 320;
            _graphics.PreferredBackBufferWidth = 240;
#endif
            _AspectRatio =(((float) _graphics.PreferredBackBufferWidth) / (float)_graphics.PreferredBackBufferHeight);
            _CurrentViewport = new Rectangle(0, (int) _WorldExtent.Y - _graphics.PreferredBackBufferWidth , _graphics.PreferredBackBufferWidth, _graphics.PreferredBackBufferHeight);


            TargetElapsedTime = TimeSpan.FromSeconds(1 / 30.0);

            Components.Add(new GamerServicesComponent(this));
        }

        public new GraphicsDeviceManager GraphicsDevice
        {
            get
            {
                return _graphics;
            }
        }

        public ContentManager ContentManager
        {
            get
            {
                return _content;
            }
        }


        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            
#if !ZUNE
            _graphics.GraphicsDevice.RenderState.DepthBufferEnable = false;
#endif
            //_graphics.GraphicsDevice.DepthStencilBuffer = new DepthStencilBuffer(_graphics.GraphicsDevice,(int) _WorldExtent.X,(int) _WorldExtent.Y, DepthFormat.Depth24Stencil8);

            _spriteBatch = new SpriteBatch(_graphics.GraphicsDevice);
            _Menus = new List<BaseMenu>();
            base.Initialize();

            _graphics.SynchronizeWithVerticalRetrace = true;
            _graphics.GraphicsDevice.PresentationParameters.FullScreenRefreshRateInHz = 30;
        }

        Rectangle BackgroundDimensions;

        /// <summary>
        /// Load your graphics content.  If loadAllContent is true, you should
        /// load content from both ResourceManagementMode pools.  Otherwise, just
        /// load ResourceManagementMode.Manual content.
        /// </summary>
        /// <param name="LoadContent">Which type of content to load.</param>
        protected override void LoadContent()
        {
            base.LoadContent();
            SetupStorageDevice();
            //Setup Dynamic textures first so we have the most ram to work with
            IServiceProvider serviceProvider = Content.ServiceProvider;
            ContentManager cm = new ContentManager(serviceProvider);
            TerrainTextureL = cm.Load<Texture2D>(@"Content/Art/GUI/BackgroundL");
            TerrainTextureR = cm.Load<Texture2D>(@"Content/Art/GUI/BackgroundR");

            BackgroundDimensions = new Rectangle(0, 0, TerrainTextureL.Width + TerrainTextureR.Width, TerrainTextureR.Height);

            int EdgeOffset = (Terrain.EdgeOffset / 10) * 2;

            MiniMap = new Texture2D(_graphics.GraphicsDevice, (BackgroundDimensions.Width / 10) - EdgeOffset, BackgroundDimensions.Height / 10, 1, TextureUsage.AutoGenerateMipMap, SurfaceFormat.Color);

            PContentManager.Instance.Load<Texture2D>(@"Content/Art/MiniMap/Team1");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/MiniMap/Team2");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/MiniMap/Team3");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/MiniMap/Team4");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/MiniMap/MiniMapYou");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/MiniMap/TerrainPiece");

            PContentManager.Instance.SetupDynamicContent(_graphics.GraphicsDevice,"whitebox");
            PContentManager.Instance.SetupSinglePixel(_graphics.GraphicsDevice, "pixel");

            PContentManager.Instance.Load<SpriteFont>(@"Content/Art/Fonts/TimeFont");
            PContentManager.Instance.Load<SpriteFont>(@"Content/Art/Fonts/INVADER");
            PContentManager.Instance.Load<SpriteFont>(@"Content/Art/Fonts/Irken");

            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/WalkLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/WalkRight");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/StandLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/StandRight");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/AimLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/AimRight");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/ShootLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/ShootRight");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/Cluster");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/ClusterGrenade");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/ClusterLauncherLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/ClusterLauncherRight");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/FlamethrowerLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/FlamethrowerRight");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/RocketLauncherLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/RocketLauncherRight");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/MineLauncherLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/MineLauncherRight");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/SpiderMineLauncherLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/SpiderMineRight");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/SpiderMineLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/SpiderMine");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/SpiderMineLauncherRight");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/NapalmLauncherLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/NapalmLauncherRight");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/Mine");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/Napalm");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/NapalmPiece");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/FlameThrowerMask");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/JetPackActiveLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/JetPackActiveRight");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/NapalmFireBig");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/NapalmFireSmall");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/NapalmFireMed");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/WeaponMenuBack");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/JetPackInactiveLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/JetPackInactiveRight");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/CollidingBox");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/Explosion1");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/Explosion1mask");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/Explosion3");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/Explosion3mask");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/NapalmMask");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/Explosion2");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/Grenade");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/FlameLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/FlameRight");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/GrenadeLauncherLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/GrenadeLauncherRight");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/HealthPack");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/Reticle");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/WeaponCollision");


            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/RocketLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/RocketRight");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/RodLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/RodExtendedLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/RodExtendedRight");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/RodRight");

            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/ShootLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/Sprites/ShootRight");


            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/0","0");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/1","1");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/2","2");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/3","3");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/4","4");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/5","5");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/6","6");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/7","7");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/8","8");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/9", "9");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/10", "10");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/infinity", "-1");

            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Back_active");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Back_inactive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Restart_active");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Restart_inactive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/ClusterLauncherLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/ClusterLauncherRight");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Exit_active");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Exit_inactive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/GrenadeLauncherLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/GrenadeLauncherRight");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/JetPackLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/JetPackRight");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Pick_Weapon");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/RocketLauncherLeft");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/RocketLauncherRight");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Credits_active");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Credits_inactive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/FlamethrowerActive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/FlamethrowerInactive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/NapalmActive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/NapalmInactive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/MineActive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/MineInactive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/SpiderMineActive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/SpiderMineInactive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Start_active");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Start_inactive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Players");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/AIPlayers");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Credits");

            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/MainMenuBackground");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/MenuBackground");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Options_active");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Options_inactive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Network_active");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Network_inactive");
            //PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Host_active");
            //PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Host_inactive");
            //PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Join_active");
            //PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Join_inactive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Local_active");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Local_inactive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/0p_active");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/0p_inactive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/1p_active");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/1p_inactive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/2p_active");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/2p_inactive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/3p_active");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/3p_inactive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/4p_active");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/4p_inactive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Randomize_active");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Randomize_inactive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Next_active");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Next_inactive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Previous_active");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Previous_inactive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Played_active");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Played_inactive");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Select_level");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Minimap_overlay");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/GameOverBackground");

            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Overlay_top");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Overlay_left");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Overlay_right");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Overlay_bottom");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Overlay_map");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/GUI/Arrow");

            PContentManager.Instance.Load<Texture2D>(@"Content/Art/MiniMap/Team1");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/MiniMap/Team2");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/MiniMap/Team3");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/MiniMap/Team4");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/MiniMap/MiniMapYou");
            PContentManager.Instance.Load<Texture2D>(@"Content/Art/MiniMap/mini_screen");
            PContentManager.Instance.SaveContent<Texture2D>(MiniMap, "MiniMap");

            TeamManager.Instance.LoadContent();

            //PContentManager.Instance.SaveContent<Texture2D>(SetupLineTexture(), "1WhitePixel");
            this._Menus.Add(new MainMenu());  
        }

        Texture2D TerrainTextureL;
        Texture2D TerrainTextureR;
        Texture2D MiniMap;
        DynamicLevel _CurrentLevel;
        BaseCollision _Collision;
        public void LoadNetworkGame(Triplet<Team, PlayerIndex,TeamType>[] teamsList,TerrainSaver ts, NetworkManager nm)
        {
            NetworkManager.Instance.Update();
            //@@ reset teams to correct names
            List<Triplet<Team, PlayerIndex, TeamType>> teams = new List<Triplet<Team, PlayerIndex, TeamType>>();
            foreach (Triplet<Team, PlayerIndex, TeamType> p in teamsList)
            {
                if(p.First != Team.NoTeam)
                {
                    teams.Add(p);
                }
            }

            _CurrentLevel = null;
            _Collision = null;
            _CurrentGameManager = null;
            
            System.GC.Collect();

            _Collision = new FakeCollision(); 

            _CurrentLevel = new DynamicLevel( TerrainTextureL,TerrainTextureR, MiniMap, _Collision, ts);

            _CurrentGameManager = new NetworkGameManager(teams, _CurrentLevel, _Collision, nm);

            System.GC.Collect();
            NetworkManager.Instance.Update();
        }

        public void LoadGame(Triplet<Team, PlayerIndex, TeamType>[] teamsList, TerrainSaver ts)
        {
            //@@ reset teams to correct names
            List<Triplet<Team, PlayerIndex, TeamType>> teams = new List<Triplet<Team, PlayerIndex, TeamType>>();
            foreach (Triplet<Team, PlayerIndex, TeamType> p in teamsList)
            {
                if (p.First != Team.NoTeam)
                {
                    teams.Add(p);
                }
            }

            _CurrentLevel = null;
            _Collision = null;
            _CurrentGameManager = null;

            System.GC.Collect();

#if ZUNE
#if PERPIXEL
            _Collision = new DeformedTerrain();
#else
            _Collision = new FakeCollision(); 
#endif
#else
            _Collision = new FakeCollision();
#endif
            _CurrentLevel = new DynamicLevel(TerrainTextureL,TerrainTextureR, MiniMap, _Collision, ts);

#if EverythingHasShaders
            _CurrentGameManager = new GameManagerShadedExplosions(teams, _CurrentLevel, _Collision);
#else
            //_CurrentGameManager = new GameManagerTeamed(teams,_CurrentLevel,_Collision);
            _CurrentGameManager = new GameManagerGamePolish(teams, _CurrentLevel, _Collision);
#endif
            System.GC.Collect();
        }

        int backcount = 0; // allow for exiting
        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        /// 
        protected override void Update(GameTime gameTime)
        {

            IgnoreAllOtherFoci = false;
            seconds = (float) gameTime.TotalGameTime.TotalSeconds;
            PInput.Instance.Update();
            NetworkManager.Instance.Update();

#if !ZUNE
            if (PInput.Instance.Keyboard.Tab.State == InputWrapper.ButtonState.Held)
            {
                _debug = true;
            }
            else
            {
                _debug = false;
            }
#endif
            _time += gameTime.ElapsedRealTime;
            ++_fps;
            if (_time.Seconds >= 1.0f)
            {
                fps = "FPS:" + _fps;
                _fps = 0;
                _time = TimeSpan.Zero;
            }

            // Allows the game to exit
            if (PInput.Instance.GamePad1.Back.State == InputWrapper.ButtonState.Held)
            {
                if(++backcount == 150) // 5 Seconds
                {
                    this.Exit();
                }
            }
            else
            {
                backcount = 0;
            }

            if (_Menus.Count != 0)
            {
                _Menus[_Menus.Count - 1].Update(gameTime);
            }

            if (_CurrentGameManager != null)
            {
                    _CurrentGameManager.Update(gameTime);
            }
            EventManager.GetInstance().Update(gameTime);

            if (Slide && !IgnoreAllOtherFoci)
            {
                Vector2 current = new Vector2(_CurrentViewport.X,_CurrentViewport.Y);
                if (current != TargetPosition)
                {
                    Vector2 directionV = (TargetPosition - current);
                    if (Math.Abs(directionV.Length()) < 5.0f)
                    {
                        _CurrentViewport.X = (int)TargetPosition.X;
                        _CurrentViewport.Y = (int)TargetPosition.Y;
                        Slide = false;
                    }
                    else if (Math.Abs(directionV.Length()) < 25.0f)
                    {
                        directionV.Normalize();
                        current += (directionV * 5);

                        _CurrentViewport.X = (int)TargetPosition.X;
                        _CurrentViewport.Y = (int)TargetPosition.Y;
                    }
                    else if (Math.Abs(directionV.Length()) < 75.0f)
                    {
                        current += (directionV * 0.275f);

                        _CurrentViewport.X = (int)current.X;
                        _CurrentViewport.Y = (int)current.Y;
                    }
                    else
                    {
                        current += (directionV * 0.1275f);

                        _CurrentViewport.X = (int)current.X;
                        _CurrentViewport.Y = (int)current.Y;
                    }
                }
                else
                {
                    Slide = false;
                }
            }
#if !ZUNE
            if (_CurrentGameManager != null)
            {
                if(PInput.Instance.Keyboard.Up.State == InputWrapper.ButtonState.Held)
                {
                    _CurrentViewport.Y -= 10;
                }
                if(PInput.Instance.Keyboard.Down.State == InputWrapper.ButtonState.Held)
                {
                    _CurrentViewport.Y += 10;
                }
                if(PInput.Instance.Keyboard.Left.State == InputWrapper.ButtonState.Held)
                { 
                    _CurrentViewport.X -= 10;
                }
                if(PInput.Instance.Keyboard.Right.State == InputWrapper.ButtonState.Held)
                {
                    _CurrentViewport.X += 10;
                }
                if(PInput.Instance.Keyboard.Plus.State == InputWrapper.ButtonState.Held)
                {
                    Increase(10);
                }
                if(PInput.Instance.Keyboard.Minus.State == InputWrapper.ButtonState.Held)
                {
                    Decrease(10);
                }

#endif
                if (_CurrentViewport.Y < 0)
                    _CurrentViewport.Y = 0;
                if (_CurrentViewport.X < 0 - (_CurrentViewport.Width / 2))
                    _CurrentViewport.X = -(_CurrentViewport.Width / 2);

                if (_CurrentViewport.X > (_WorldExtent.X - (_CurrentViewport.Width / 2)))
                    _CurrentViewport.X = (int)(_WorldExtent.X - (int)(_CurrentViewport.Width / 2));
                if (_CurrentViewport.Y > (_WorldExtent.Y - _CurrentViewport.Height))
                    _CurrentViewport.Y = (int)(_WorldExtent.Y - (int)_CurrentViewport.Height);
                
#if !ZUNE
                PlayerIndex pi = (Game1.Instance._CurrentGameManager as GameManagerTeamedInterface).CurrentPlayer();

                _CurrentViewport.X += (int)(10 * Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)pi).ThumbSticks.Right.X);
                _CurrentViewport.Y -= (int)(10 * Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)pi).ThumbSticks.Right.Y);

                if (Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)pi).Buttons.RightShoulder == ButtonState.Pressed)
                {
                    Increase(10);
                }
                if (Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)pi).Buttons.LeftShoulder == ButtonState.Pressed)
                {
                    Decrease(10);
                }
            }
#endif

                base.Update(gameTime);
        }


        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            _graphics.GraphicsDevice.Clear(Color.Black);//Terrain.BackGround);
            _spriteBatch.Begin(SpriteBlendMode.None, SpriteSortMode.Immediate, SaveStateMode.None);
            if (_CurrentGameManager != null)
            {
                GameManager.Level.Draw(_spriteBatch, gameTime, _CurrentViewport);
            }
            _spriteBatch.End();
            _spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.BackToFront, SaveStateMode.None);
            if (_CurrentGameManager != null)
            {
                _CurrentGameManager.Draw(_spriteBatch, gameTime, _CurrentViewport);
            }
            _spriteBatch.DrawString(PContentManager.Instance.GetObject<SpriteFont>(@"Content/Art/Fonts/INVADER"),fps,Vector2.Zero,Color.White);
            if (_Menus.Count != 0)
            {
                _Menus[_Menus.Count - 1].Draw(_spriteBatch,gameTime);
            }

            _spriteBatch.DrawString(PContentManager.Instance.GetObject<SpriteFont>("Content/Art/Fonts/INVADER"), System.GC.GetTotalMemory(false).ToString("#,###,###,###"), new Vector2(85, 303), Color.White);

            _spriteBatch.End();

            base.Draw(gameTime);
        }
        #region DrawLine
        /*
        Texture2D spr;
        Texture2D SetupLineTexture()
        {
            spr = new Texture2D(_graphics.GraphicsDevice, 1, 4, 1, TextureUsage.AutoGenerateMipMap,SurfaceFormat.Color);
            Color[] colordata = new Color[spr.Height * spr.Width];
            spr.GetData<Color>(colordata);
            colordata[0] = Color.White;
            colordata[1] = Color.White;
            colordata[2] = Color.White;
            colordata[3] = Color.White;
            spr.SetData<Color>(colordata);
            return spr;
        }

        public void DrawLine(SpriteBatch sprBatch, Vector2 a, Vector2 b, Color col)
        {
            Vector2 Origin = new Vector2(spr.Width / 2, 0.0f);
            Vector2 diff = b - a;
            float angle;
            Vector2 Scale = new Vector2(1.0f, diff.Length());

            angle = (float)(Math.Atan2(diff.Y, diff.X)) - MathHelper.PiOver2;

            sprBatch.Draw(spr, a, null, col, angle, Origin, Scale, SpriteEffects.None, 0.0f);
        }
        */
        #endregion
    }


    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main(string[] args)
        {
            Game1.Instance.Window.Title = "";
            Game1.Instance.Run();
        }
    }
}
